const helmet = require('helmet')
const rateLimit = require('express-rate-limit')
const cors = require('cors')
const compression = require('compression')
const config = require('../config')
const logger = require('../utils/logger')
const { HTTP_STATUS, ERROR_CODES } = require('../utils/constants')

/**
 * CORS配置
 */
const corsOptions = {
  origin: function (origin, callback) {
    // 允许没有origin的请求（如移动应用）
    if (!origin) return callback(null, true)
    
    // 检查origin是否在允许列表中
    const allowedOrigins = config.cors.origin.split(',')
    if (allowedOrigins.indexOf(origin) !== -1 || allowedOrigins.includes('*')) {
      callback(null, true)
    } else {
      logger.warn('CORS blocked request', { origin })
      callback(new Error('不允许的CORS请求'))
    }
  },
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
  allowedHeaders: [
    'Origin',
    'X-Requested-With',
    'Content-Type',
    'Accept',
    'Authorization',
    'Cache-Control',
    'Pragma',
    'Range',
    'Content-Range',
    'Content-Length'
  ],
  exposedHeaders: ['X-Total-Count', 'X-Page-Count', 'Content-Range', 'Content-Length', 'Accept-Ranges'],
  maxAge: 86400 // 24小时
}

/**
 * Helmet安全配置
 */
const helmetOptions = {
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      scriptSrc: ["'self'", "'unsafe-inline'", "'wasm-unsafe-eval'", "'inline-speculation-rules'"],
      imgSrc: ["'self'", 'data:', 'https:'],
      connectSrc: ["'self'"],
      fontSrc: ["'self'"],
      objectSrc: ["'none'"],
      mediaSrc: ["'self'", 'data:', 'blob:'],
      frameSrc: ["'self'", 'data:', 'blob:']
    }
  },
  crossOriginEmbedderPolicy: false,
  // 禁用Cross-Origin-Resource-Policy以允许跨域资源访问
  crossOriginResourcePolicy: false,
  // 禁用helmet的X-Frame-Options设置，使用我们的自定义设置
  frameguard: false,
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true,
    preload: true
  }
}

/**
 * 通用速率限制
 */
const generalLimiter = rateLimit({
  windowMs: config.security.rateLimitWindowMs,
  max: config.security.rateLimitMaxRequests,
  message: {
    success: false,
    error: {
      code: ERROR_CODES.RATE_LIMIT_EXCEEDED,
      message: '请求过于频繁，请稍后再试',
      timestamp: new Date().toISOString()
    }
  },
  standardHeaders: true,
  legacyHeaders: false,
  handler: (req, res) => {
    logger.warn('Rate limit exceeded', {
      ip: req.ip,
      userAgent: req.get('User-Agent'),
      path: req.path,
      method: req.method
    })
    
    res.status(HTTP_STATUS.TOO_MANY_REQUESTS).json({
      success: false,
      error: {
        code: ERROR_CODES.RATE_LIMIT_EXCEEDED,
        message: '请求过于频繁，请稍后再试',
        timestamp: new Date().toISOString()
      }
    })
  },
  skip: (req) => {
    // 跳过健康检查和静态资源
    return req.path === '/health' || req.path.startsWith('/static')
  }
})

/**
 * 认证相关的严格速率限制
 */
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15分钟
  max: 5, // 每15分钟最多5次尝试
  message: {
    success: false,
    error: {
      code: ERROR_CODES.RATE_LIMIT_EXCEEDED,
      message: '登录尝试过于频繁，请15分钟后再试',
      timestamp: new Date().toISOString()
    }
  },
  standardHeaders: true,
  legacyHeaders: false,
  skipSuccessfulRequests: true, // 成功的请求不计入限制
  handler: (req, res) => {
    logger.warn('Auth rate limit exceeded', {
      ip: req.ip,
      userAgent: req.get('User-Agent'),
      path: req.path
    })
    
    res.status(HTTP_STATUS.TOO_MANY_REQUESTS).json({
      success: false,
      error: {
        code: ERROR_CODES.RATE_LIMIT_EXCEEDED,
        message: '登录尝试过于频繁，请15分钟后再试',
        timestamp: new Date().toISOString()
      }
    })
  }
})

/**
 * AI API调用速率限制
 */
const aiLimiter = rateLimit({
  windowMs: 60 * 1000, // 1分钟
  max: 20, // 每分钟最多20次AI调用
  message: {
    success: false,
    error: {
      code: ERROR_CODES.RATE_LIMIT_EXCEEDED,
      message: 'AI调用过于频繁，请稍后再试',
      timestamp: new Date().toISOString()
    }
  },
  standardHeaders: true,
  legacyHeaders: false,
  keyGenerator: (req) => {
    // 基于用户ID限制，如果没有用户ID则使用IP
    return req.user?.id || req.ip
  },
  handler: (req, res) => {
    logger.warn('AI rate limit exceeded', {
      userId: req.user?.id,
      ip: req.ip,
      userAgent: req.get('User-Agent')
    })
    
    res.status(HTTP_STATUS.TOO_MANY_REQUESTS).json({
      success: false,
      error: {
        code: ERROR_CODES.RATE_LIMIT_EXCEEDED,
        message: 'AI调用过于频繁，请稍后再试',
        timestamp: new Date().toISOString()
      }
    })
  }
})

/**
 * 请求大小限制中间件
 */
const requestSizeLimit = (req, res, next) => {
  const contentLength = parseInt(req.get('Content-Length') || '0')
  const maxSize = config.security.maxRequestSize
  
  if (contentLength > maxSize) {
    logger.warn('Request size exceeded', {
      contentLength,
      maxSize,
      ip: req.ip,
      path: req.path
    })
    
    return res.status(HTTP_STATUS.PAYLOAD_TOO_LARGE).json({
      success: false,
      error: {
        code: ERROR_CODES.FILE_TOO_LARGE,
        message: `请求体过大，最大允许 ${Math.round(maxSize / 1024 / 1024)}MB`,
        timestamp: new Date().toISOString()
      }
    })
  }
  
  next()
}

/**
 * IP白名单中间件
 */
const ipWhitelist = (whitelist = []) => {
  return (req, res, next) => {
    if (whitelist.length === 0) {
      return next()
    }
    
    const clientIP = req.ip || req.connection.remoteAddress
    
    if (!whitelist.includes(clientIP)) {
      logger.warn('IP not in whitelist', {
        ip: clientIP,
        path: req.path,
        method: req.method
      })
      
      return res.status(HTTP_STATUS.FORBIDDEN).json({
        success: false,
        error: {
          code: ERROR_CODES.ACCESS_DENIED,
          message: 'IP地址不在允许列表中',
          timestamp: new Date().toISOString()
        }
      })
    }
    
    next()
  }
}

/**
 * 请求日志中间件
 */
const requestLogger = (req, res, next) => {
  const start = Date.now()
  
  // 记录请求开始
  logger.info('Request started', {
    method: req.method,
    url: req.url,
    ip: req.ip,
    userAgent: req.get('User-Agent'),
    userId: req.user?.id,
    timestamp: new Date().toISOString()
  })
  
  // 监听响应结束
  res.on('finish', () => {
    const duration = Date.now() - start
    
    logger.info('Request completed', {
      method: req.method,
      url: req.url,
      statusCode: res.statusCode,
      duration: `${duration}ms`,
      ip: req.ip,
      userId: req.user?.id,
      timestamp: new Date().toISOString()
    })
  })
  
  next()
}

/**
 * 健康检查中间件
 */
const healthCheck = (req, res, next) => {
  if (req.path === '/health') {
    return res.json({
      success: true,
      data: {
        status: 'healthy',
        timestamp: new Date().toISOString(),
        uptime: process.uptime(),
        memory: process.memoryUsage(),
        version: process.env.npm_package_version || '1.0.0'
      }
    })
  }
  next()
}

/**
 * 安全头中间件
 */
const securityHeaders = (req, res, next) => {
  // 移除敏感的服务器信息
  res.removeHeader('X-Powered-By')
  
  // 添加自定义安全头
  res.setHeader('X-Content-Type-Options', 'nosniff')
  // 完全移除X-Frame-Options以允许视频在任何frame中播放 - 解决 net::ERR_BLOCKED_BY_RESPONSE 错误
  // res.setHeader('X-Frame-Options', 'SAMEORIGIN') // 注释掉以允许跨域frame
  res.setHeader('X-XSS-Protection', '1; mode=block')
  res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin')
  res.setHeader('Permissions-Policy', 'geolocation=(), microphone=(), camera=()')
  
  next()
}

/**
 * 压缩配置
 */
const compressionOptions = {
  filter: (req, res) => {
    // 不压缩已经压缩的内容
    if (req.headers['x-no-compression']) {
      return false
    }
    
    // 使用compression的默认过滤器
    return compression.filter(req, res)
  },
  threshold: 1024, // 只压缩大于1KB的响应
  level: 6, // 压缩级别 (1-9)
  memLevel: 8 // 内存级别 (1-9)
}

module.exports = {
  // 中间件函数
  cors: cors(corsOptions),
  helmet: helmet(helmetOptions),
  compression: compression(compressionOptions),
  generalLimiter,
  authLimiter,
  aiLimiter,
  requestSizeLimit,
  ipWhitelist,
  requestLogger,
  healthCheck,
  securityHeaders,
  
  // 配置对象
  corsOptions,
  helmetOptions,
  compressionOptions
}